package com.itlong.cloud.controller.mine;

import com.alibaba.fastjson.JSONArray;
import com.itlong.cloud.POJO.DTO.app.AppImageDTO;
import com.itlong.cloud.POJO.DTO.app.property.app.PropertyAppFeedbackInfoDTO;
import com.itlong.cloud.POJO.DTO.app.property.app.PropertyAppImageDTO;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.app.property.app.PropertyAppFeedbackInfoVO;
import com.itlong.cloud.POJO.VO.property.PropertyUserCacheVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.abstracts.BaseController;
import com.itlong.cloud.annotation.LoggerInfo;
import com.itlong.cloud.constants.LogDescConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.FileCatalogEnum;
import com.itlong.cloud.enumerate.ecode.AppErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.BaseErrorCodeEnum;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.user.propertyapp.IPropertyAppUserInfoServiceClient;
import com.itlong.cloud.utils.encrypt.UserTokenUtil;
import com.itlong.cloud.utils.file.UploadFileUtil;
import com.itlong.cloud.utils.network.http.HttpProtocolUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.words.NumberHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import sun.misc.BASE64Decoder;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <desc>
 * 物业APP我的-用户操作控制器
 * </desc>
 *
 * @createDate2020/1/13
 **/
@RestController
@RequestMapping("/user")
@RefreshScope
public class PropertyAppUserController extends BaseController {
    private static Logger LOG = LoggerFactory.getLogger(PropertyAppUserController.class);

    @Value("${" + PlatformConstants.PROPERTY_APP_MD5_ENCRYPT_KEY + "}")
    private String PROPERTY_APP_MD5_ENCRYPT_KEY;

    @Value("${" + PlatformConstants.PROPERTY_APP_USER_TOKEN_KEY + "}")
    private String PROPERTY_APP_USER_TOKEN_KEY;

    @Value("${" + PlatformConstants.FILE_FTP_HOST + "}")
    public String FILE_FTP_HOST;
    @Value("${" + PlatformConstants.FILE_FTP_PORT + "}")
    public String FILE_FTP_PORT;
    @Value("${" + PlatformConstants.FILE_FTP_USERNAME + "}")
    public String FILE_FTP_USERNAME;
    @Value("${" + PlatformConstants.FILE_FTP_PASSWORD + "}")
    public String FILE_FTP_PASSWORD;
    @Value("${" + PlatformConstants.FILE_ACCESS_URL + "}")
    public String FILE_ACCESS_URL;

    @Autowired
    private IPropertyAppUserInfoServiceClient propertyAppUserInfoServiceClient;

    @Autowired
    private RedisService<PropertyUserCacheVO> redisService;

    /**
     * <desc>
     * 更改头像地址
     * </desc>
     *
     * @param token     登录凭证
     * @param imageStr  头像二进制编码
     * @param imageType 图片类型
     * @return 头像地址
     * @Author Zhu.yj
     * @createDate 2020/1/10
     */
    @ResponseBody
    @RequestMapping(value = "/updatePhoto", method = RequestMethod.POST)
    public Object updatePhoto(String token, String imageStr, String imageType, HttpServletRequest request) {
        try {
            imageStr = request.getAttribute("imageStr") == null ? null : request.getAttribute("imageStr").toString();
            imageType = request.getAttribute("imageType") == null ? null : request.getAttribute("imageType").toString();
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            if (StringUtils.isBlank(imageStr) || StringUtils.isBlank(imageType) || StringUtils.isBlank(token)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            PropertyUserCacheVO propertyUserCacheVO = propertyAppUserInfoServiceClient.retrieve(token);
            //更改该用户头像地址
            String uploadFilePath = uploadImageFile(imageStr, imageType, FileCatalogEnum.PROPERTY_APP_HEAD_PICTURE_FILE);
            Map<String, Object> params = new HashMap<>();
            params.put("userId", propertyUserCacheVO.getUserId());
            params.put("imageStr", uploadFilePath);
            Integer result = propertyAppUserInfoServiceClient.updatePhotoOrName(params);
            //更新缓存
            if (result > 0) {
                propertyUserCacheVO.setPhotoUrl(uploadFilePath);
                redisService.set(RedisConstant.PROPERTY_APP_REDIS_USER_KEY + propertyUserCacheVO.getUserId(), RedisConstant.PROPERTY_APP_LOGIN_TIME, propertyUserCacheVO);
            }
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("photoUrl",uploadFilePath);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), resultMap);
        } catch (Exception e) {
            throw new DataAccessException("【物业app-我的-更改头像地址updatePhoto】更改头像地址失败", e);
        }
    }

    /**
     * <desc>
     * 更新昵称
     * </desc>
     *
     * @param token    用户登陆凭证
     * @param nickName 用户昵称
     * @return
     * @Author Zhu.yj
     * @createDate 2020/1/10
     */
    @ResponseBody
    @RequestMapping(value = "/updateNickName", method = RequestMethod.POST)
    public Object updateNickName(String token, String nickName, HttpServletRequest request) {
        try {
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            nickName = request.getAttribute("nickName") == null ? null : request.getAttribute("nickName").toString();
            if (StringUtils.isBlank(nickName)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String userId = UserTokenUtil.newAPPTokenDecrypt(token, PROPERTY_APP_USER_TOKEN_KEY);
            Map<String, Object> params = new HashMap<>();
            params.put("userId", userId);
            params.put("nickName", nickName);
            //更新昵称
            Integer result = propertyAppUserInfoServiceClient.updatePhotoOrName(params);

            PropertyUserCacheVO propertyUserCacheVO = propertyAppUserInfoServiceClient.retrieve(token);
            propertyUserCacheVO.setRealName(nickName);
            //更新缓存
            if (result > 0) {
                redisService.set(RedisConstant.PROPERTY_APP_REDIS_USER_KEY + userId, RedisConstant.PROPERTY_APP_LOGIN_TIME, propertyUserCacheVO);
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【物业APP-我的-更新昵称updateNickName】更新昵称失败", e);
        }
    }

    /**
     * <desc>
     * 获取用户通行记录
     * </desc>
     *
     * @param token     用户登陆凭证
     * @param projectId 项目id
     * @param pageIndex 当前页数
     * @return 通行记录分页列表
     * @Author Zhu.yj
     * @createDate 2020/1/13
     */
    @RequestMapping(value = "/getOpenDoorRecord", method = RequestMethod.POST)
    public Object getOpenDoorRecord(String token, String projectId, String pageIndex, HttpServletRequest request) {
        try {
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            pageIndex = request.getAttribute("pageIndex") == null ? null : request.getAttribute("pageIndex").toString();
            if (StringUtils.isBlank(token) || StringUtils.isBlank(pageIndex)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            if (StringUtils.isBlank(projectId) || !projectId.matches("[0-9]{8}")) {
                return new MessageVO(AppErrorCodeEnum.PROJECT_NOT_MATCH.getErrorCode());
            }
            PropertyUserCacheVO propertyUserCacheVO = propertyAppUserInfoServiceClient.retrieve(token);
            Map<String, Object> resultMap = propertyAppUserInfoServiceClient.getPassRecordPage(projectId, pageIndex, propertyUserCacheVO.getUserId());
            if (resultMap.size() != 0) {
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), resultMap);
            }
            return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【物业APP我的-用户操作-获取通行记录getOpenDoorRecord】获取通行记录失败", e);
        }
    }

    /**
     * <desc>
     * 添加反馈
     * </desc>
     *
     * @param
     * @return
     * @Author Zhu.yj
     * @createDate 2020/1/15
     */
    @ResponseBody
    @RequestMapping(value = "/feedback/add", method = RequestMethod.POST)
    public Object saveFeedback(PropertyAppFeedbackInfoDTO propertyAppFeedbackInfoDTO, HttpServletRequest request) {
        try {
            propertyAppFeedbackInfoDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyAppFeedbackInfoDTO.class, request);
            if (propertyAppFeedbackInfoDTO == null || StringUtils.isBlank(propertyAppFeedbackInfoDTO.getProjectId())
                    || StringUtils.isBlank(propertyAppFeedbackInfoDTO.getAppVersion()) || StringUtils.isBlank(propertyAppFeedbackInfoDTO.getFeedbackInfo())
                    || StringUtils.isBlank(propertyAppFeedbackInfoDTO.getPhoneModel())) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            if (!NumberHandlerUtil.isInRange(propertyAppFeedbackInfoDTO.getProblemType(), 1, 2)) {
                return new MessageVO(BaseErrorCodeEnum.PARAM_ERR.getErrorCode());
            }
            if (!propertyAppFeedbackInfoDTO.getProjectId().matches("[0-9]{8}")) {
                return new MessageVO(AppErrorCodeEnum.PROJECT_NOT_MATCH.getErrorCode());
            }
            //处理表单图片
            if (StringUtils.isNotBlank(propertyAppFeedbackInfoDTO.getImageAry())) {
                List<PropertyAppImageDTO> appImageDTOList = JSONArray.parseArray(propertyAppFeedbackInfoDTO.getImageAry(), PropertyAppImageDTO.class);
                LOG.info(appImageDTOList.toString());
                String feedbackImageUrl = "";
                for (PropertyAppImageDTO appImageDTO : appImageDTOList) {
                    String imageUrl = this.uploadImageFile(appImageDTO.getImageUrl(), appImageDTO.getImageType(), FileCatalogEnum.PROPERTY_APP_FEEDBACK_PICTURE_FILE);
                    if ("".equals(feedbackImageUrl)){
                        feedbackImageUrl += imageUrl;
                    }else {
                        feedbackImageUrl += ","+ imageUrl;
                    }
                }
                propertyAppFeedbackInfoDTO.setImageUrl(feedbackImageUrl);
            }
            PropertyUserCacheVO propertyUserCacheVO = propertyAppUserInfoServiceClient.retrieve(propertyAppFeedbackInfoDTO.getToken());
            propertyAppFeedbackInfoDTO.setUserId(propertyUserCacheVO.getUserId());
            if (propertyAppUserInfoServiceClient.saveFeedback(propertyAppFeedbackInfoDTO) > 0) {
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
            }
            return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【物业APP我的-用户操作-添加反馈addFeedback】添加反馈失败", e);
        }
    }

    /**
     * <desc>
     * 获取历史反馈信息
     * </desc>
     *
     * @param token     用户登录凭证
     * @param projectId 项目id
     * @param request
     * @return
     * @Author Zhu.yj
     * @createDate 2020/1/15
     */
    @ResponseBody
    @RequestMapping(value = "/historyFeedback", method = RequestMethod.POST)
    public Object historyFeedback(String token, String projectId,String pageNum, HttpServletRequest request) {
        try {
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            pageNum = request.getAttribute("pageNum") == null ? null : request.getAttribute("pageNum").toString();
            if (StringUtils.isBlank(token) || StringUtils.isBlank(projectId) || StringUtils.isBlank(pageNum)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            PropertyUserCacheVO propertyUserCacheVO = propertyAppUserInfoServiceClient.retrieve(token);
            if (StringUtils.isBlank(propertyUserCacheVO.getUserId())) {
                return new MessageVO(BaseErrorCodeEnum.PARAM_ERR.getErrorCode());
            }
            Map<String,Object> result = propertyAppUserInfoServiceClient.getHistoryFeedback(propertyUserCacheVO.getUserId(), projectId,pageNum);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), result);
        } catch (Exception e) {
            throw new DataAccessException("【物业app-我的-获取用户历史反馈historyFeedback】获取用户历史反馈失败", e);
        }
    }

    /**
     * <desc>
     * 上传常用楼层
     * </desc>
     *
     * @param projectId    项目编号
     * @param deviceUnique 设备序列号
     * @param liveFloor    常用楼层名称
     * @return 标准格式化响应结果
     * @author Juguang.S
     * @createDate 2020/01/15
     */
    @ResponseBody
    @PostMapping(path = "upLoadUseFloor")
    @LoggerInfo(operateDesc = LogDescConstant.UPLOAD_CHOICE_FLOOR_DESC)
    public Object uploadChoiceFloor(String projectId, String deviceUnique, String liveFloor, String token, String language, String createTime, String sign) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            deviceUnique = request.getAttribute("deviceUnique") == null ? null : request.getAttribute("deviceUnique").toString();
            liveFloor = request.getAttribute("liveFloor") == null ? "" : request.getAttribute("liveFloor").toString();
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            if (StringUtils.isBlank(projectId) || StringUtils.isBlank(deviceUnique) || StringUtils.isBlank(token) || StringUtils.isBlank(liveFloor)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            // 从缓存中获取用户信息
            PropertyUserCacheVO propertyUserCacheVO = propertyAppUserInfoServiceClient.retrieve(token);
            propertyAppUserInfoServiceClient.uploadChoiceFloor(projectId, deviceUnique, liveFloor, propertyUserCacheVO.getUserId());
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【物业APP_我的版块】上传常用楼层失败", e);
        }
    }

    /**
     * <desc>
     *      上传图片文件
     * <desc/>
     *
     * @param imageStr 图片二进制
     * @param imageType 图片类型
     * @return
     * @author Chunjian.G
     * @createDate 2017-11-10
     */
    private String uploadImageFile(String imageStr,String imageType, FileCatalogEnum fileCatalog){
        try {
            imageStr = URLDecoder.decode(imageStr, "UTF-8");
        }catch (Exception e){
            LOG.info("imageStr URLDecoder失败", e);
            return null;
        }
        byte[] bytes = null;
        try {
            bytes = new BASE64Decoder().decodeBuffer(imageStr);
        } catch (IOException e) {
            LOG.info("BASE64Decoder().decodeBuffer失败,imageStr不合法", e);
            return null;
        }
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        UploadFileUtil.UploadFile uploadFileUtil = new UploadFileUtil().new UploadFile(
                FILE_FTP_HOST,
                FILE_FTP_USERNAME,
                FILE_FTP_PASSWORD,
                FILE_FTP_PORT,
                byteArrayInputStream,
                imageType,
                FILE_ACCESS_URL,
                fileCatalog.getType()
        );
        try {
            LOG.info("正在上传图片");
            Map<String, Object> resultMap = UploadFileUtil.uploadFile(uploadFileUtil);
            LOG.info("图片上传完毕");
            String returnCode = resultMap.get("returnCode").toString();
            if ("true".equals(returnCode)){
                String fileUrl = resultMap.get("accessPath").toString();
                return fileUrl;
            }else {
                LOG.info(String.format("图片上传失败，returnCode: %s",returnCode));
                return null;
            }
        } catch (IOException e) {
            LOG.info("UploadFileUtil.uploadFile失败", e);
            return null;
        }
    }
}
